package tx面试;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

 class alternatingPrinter2 {

    // 创建可重入锁及两个 Condition
    private static ReentrantLock lock = new ReentrantLock();
    // 数字线程等待条件
    private static Condition conditionNumber = lock.newCondition();
    // 字母线程等待条件
    private static Condition conditionLetter = lock.newCondition();



    private static boolean numberTurn = true;

    private static final int MAX_NUMBER = 3; // 打印数字 1~3
    private static final int MAX_LETTER = 'C'; // 打印字母 A~C

    public static void main(String[] args) {
        Thread threadNumber = new Thread(new NumberPrinter());
        Thread threadLetter = new Thread(new LetterPrinter());

        threadNumber.start();
        threadLetter.start();
    }

    // 打印数字的线程
    static class NumberPrinter implements Runnable {
        @Override
        public void run() {
            for (int i = 1; i <= MAX_NUMBER; i++) {
                lock.lock();
                try {
                    // 如果不是数字打印的时机，则等待
                    while (!numberTurn) {
                        conditionNumber.await();
                    }
                    // 打印数字
                    System.out.print(i + " ");
                    // 修改标志，轮到字母线程打印
                    numberTurn = false;
                    // 通知字母线程
                    conditionLetter.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    // 打印字母的线程
    static class LetterPrinter implements Runnable {
        @Override
        public void run() {
            for (char c = 'A'; c <= (char) MAX_LETTER; c++) {
                lock.lock();
                try {
                    while (numberTurn) {
                        conditionLetter.await();
                    }
                    System.out.print(c + " ");

                    numberTurn = true;

                    conditionNumber.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }
}
